// i.r(t), i.d(t, { default: () => FloorDataModule })
import * as THREE from "three"
import DataSyncStore from "../storage/DataSyncStore"
import Module from "./Module"
import aggregationTypeEnum from "../enum/aggregationType.enum"
import MapMonitor from "../collection/MapMonitor"
import FloorsData from "../data/FloorsData"
import MeshData from "../data/MeshData"
import { SaveCommand } from "../command/data.command"
import SweepData from "../data/SweepData"
import Logger from "../utils/Logger"

import Floor from "../object/Floor"

import Store from "../storage/Store"
import { CollectionSync } from "../storage/DataSync"
import { InvalidFloorException } from "../exception/floor.exception"
import funcUtil from "../utils/func.util"
const A = e => e.replace(/,/gi, " ").trim()
const deserialize = e => {
    if (!e || !e.floors) return null
    const t = {}
    return (
      e.floors.split(",").forEach((e, i) => {
        const n = e.trim()
        ;(n || "" === n) &&
          (t[i] = new Floor({
            id: String(i),
            name: n,
            meshGroup: i,
            index: i
          }))
      }),
      t
    )
  },
  D = (e, t) => {
    const i = funcUtil.deepCopy(e)
    funcUtil.merge(i, t)
    const n = []
    for (const e in i) {
      const t = i[e]
      if (!t) continue
      const s = A(t.name || ""),
        r = parseInt(e, 10)
      if (isNaN(r)) throw new InvalidFloorException(`Can't save non-numeric floor ID ${r}`)
      n[r] = s
    }
    return { floors: n.join(",") }
  }
import sweepAlignmentEnum from "../enum/sweepAlignment.enum"
import storageTypeEnum from "../enum/storageType.enum"
import dataTypeEnum from "../enum/dataType.enum"
import { SweepFloorOverrideMessage } from "../message/sweeps.messge"
const P = new Logger("floors-data")
export default class FloorDataModule extends Module {
  engine: any
  store: DataSyncStore
  data: FloorsData
  monitor: MapMonitor<any>
  constructor() {
    super(...arguments), (this.name = "floors")
  }
  async init(e, t) {
    const { readonly: i } = e
    ;(this.engine = t), (this.store = this.configureStorage(e))
    const [n, r, a] = await Promise.all([this.store.read(), t.market.waitForData(MeshData), t.market.waitForData(SweepData)]),
      f = a.getSweepList()
    this.data = new FloorsData(n || {})
    const v = this.data.mapMeshesToFloors([...r.meshGroups.floors])
    if (
      (r.setMeshIds({ floorIdMap: v }),
      this.mapSweepsToFloors(f),
      t.market.register(this, FloorsData, this.data),
      this.fixupSweepsWithoutFloorData(f),
      !1 === i)
    ) {
      const e = this.data.getCollection()
      ;(this.monitor = new MapMonitor(e, { aggregationType: aggregationTypeEnum.NextFrame }, t)),
        this.monitor.onChanged(() => this.engine.commandBinder.issueCommand(new SaveCommand({ dataTypes: [dataTypeEnum.FLOORS] }))),
        this.store instanceof DataSyncStore && this.store.addMonitor(this.monitor)
    }
  }
  configureStorage(e) {
    const { modelId, baseUrl, queue } = e,
      r = e.storageProvider || storageTypeEnum.JSONSTORE,
      o = !("readonly" in e) || !!e.readonly
    P.info(`Loading floors from ${r}`)
    const path = `${baseUrl}/scene-portal/api/v1/player/models/${modelId}`
    const store = new Store.ReadOnlyStore({
      queue,
      path,
      deserialize,
      cachedData: { data: null }
    })
    const sync = new CollectionSync({ publishStores: [store] })
    return new DataSyncStore(sync, {
      dataType: dataTypeEnum.FLOORS,
      engine: this.engine
    })
  }
  onUpdate() {}
  mapSweepsToFloors(e) {
    e.forEach(e => {
      if (e.alignmentType === sweepAlignmentEnum.ALIGNED) {
        let t
        ;(t = e.floorId && this.data.hasFloor(e.floorId) ? this.data.getFloor(e.floorId) : this.data.getClosestFloorAtHeight(e.position.y)), t && t.addSweep(e)
      }
    })
  }
  fixupSweepsWithoutFloorData(e) {
    const t = new THREE.Vector3()
    for (const i of e)
      if (null === i.floorId || !this.data.hasFloor(i.floorId)) {
        t.setY(i.position.y)
        const e = this.data.getFloorAtHeight(i.position.y)
        ;(null == e ? void 0 : e.id) &&
          e.id !== i.floorId &&
          (P.debug(`Setting ${i.alignmentType} sweep ${i.id} from floor ${i.floorId} to ${e.id}`),
          this.engine.broadcast(new SweepFloorOverrideMessage(i, i.floorId, i.floorId)),
          (i.floorId = e.id))
      }
  }
  getFloorMins() {
    const e = []
    return (
      this.data.iterate(t => {
        e.push(t.bottom)
      }),
      e
    )
  }

  async revert() {
    if (this.store instanceof DataSyncStore) return this.store.revert()
  }
}
